﻿
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports osi.root.constants
Imports osi.root.connector
Imports osi.root.procedure
Imports osi.root.formation
Imports osi.root.utils
Imports osi.root.lock
Imports osi.root.envs
Imports osi.service.dns

'create connections for a powerpoint
Public Class connector
    Private Shared Function verify_token(ByVal p As powerpoint, ByVal c As TcpClient) As event_comb
        assert(Not p Is Nothing)
        assert(Not c Is Nothing)
        Dim ec As event_comb = Nothing
        Dim rec As pointer(Of Byte()) = Nothing
        Return New event_comb(Function() As Boolean
                                  If String.IsNullOrEmpty(p.token) Then
                                      Return goto_end()
                                  Else
                                      rec = New pointer(Of Byte())()
                                      ec = (New questioner(c, p))(str_bytes(p.token), rec)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  If Not ec.end_result() OrElse
                                     isemptyarray(+rec) OrElse
                                     Not strsame(bytes_str(+rec), p.token) Then
                                      If tcp_trace Then
                                          raise_error(p.identity(),
                                                      " actively reject the token ",
                                                      p.token,
                                                      ", response is ",
                                                      bytes_str(+rec),
                                                      ", will close the connection ",
                                                      c.identity())
                                      End If
                                      Return False
                                  Else
                                      Return goto_end()
                                  End If
                              End Function)
    End Function

    Private Shared Function generate_connection(ByVal add As IPAddress,
                                                ByVal p As powerpoint,
                                                ByVal r As pointer(Of TcpClient)) As event_comb
        assert(Not add Is Nothing)
        assert(Not p Is Nothing)
        assert(p.is_outgoing)
        Dim ec As event_comb = Nothing
        Dim c As TcpClient = Nothing
        Return New event_comb(Function() As Boolean
                                  c = New TcpClient(If(p.ipv4,
                                                       AddressFamily.InterNetwork,
                                                       AddressFamily.InterNetworkV6))
                                  c.set_no_delay(True)
                                  ec = _tcpclient.connect(c, New IPEndPoint(add, p.port))
                                  Return waitfor(ec, p.connecting_timeout_ms) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  If ec.end_result() Then
                                      ec = verify_token(p, c)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  Else
                                      If tcp_trace Then
                                          raise_error(error_type.warning,
                                                      "failed to connect to ",
                                                      p.identity())
                                      End If
                                      c.shutdown()
                                      Return False
                                  End If
                              End Function,
                              Function() As Boolean
                                  assert(Not c Is Nothing)
                                  If ec.end_result() Then
                                      Return eva(r, c) AndAlso
                                             goto_end()
                                  ElseIf tcp_trace Then
                                      raise_error(error_type.warning,
                                                  "failed to verify token for ",
                                                  p.identity())
                                  End If
                                  c.shutdown()
                                  Return False
                              End Function)
    End Function

    Public Shared Function generate_connection(ByVal p As powerpoint,
                                               ByVal r As pointer(Of TcpClient)) As event_comb
        Dim ec As event_comb = Nothing
        Dim add As pointer(Of IPAddress) = Nothing
        Return New event_comb(Function() As Boolean
                                  If p Is Nothing Then
                                      Return False
                                  Else
                                      add = New pointer(Of IPAddress)()
                                      ec = If(p.ipv4,
                                              resolve_ipv4(p.host_or_ip, add),
                                              resolve_ipv6(p.host_or_ip, add))
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  If ec.end_result() AndAlso
                                     Not (+add) Is Nothing Then
                                      ec = generate_connection(+add, p, r)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  Else
                                      If tcp_trace Then
                                          raise_error(error_type.warning,
                                                      "failed to resolve host or ip ",
                                                      p.host_or_ip,
                                                      " to ip address for ",
                                                      p.identity())
                                      End If
                                      Return False
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)

    End Function
End Class
